package com.boot.security.server.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 文件工具类
 * @author Ming
 */
@Slf4j
public class FileUtil {

    public static String saveFile (MultipartFile file, String pathname) {
        try {
            File targetFile = new File(pathname);
            if (targetFile.exists()) {
                return pathname;
            }
            if (! targetFile.getParentFile().exists()) {
                targetFile.getParentFile().mkdirs();
            }
            file.transferTo(targetFile);
            return pathname;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static boolean deleteFile (String pathname) {
        File file = new File(pathname);
        if (file.exists()) {
            boolean flag = file.delete();
            if (flag) {
                File[] files = file.getParentFile().listFiles();
                if (files == null || files.length == 0) {
                    file.getParentFile().delete();
                }
            }
            return flag;
        }
        return false;
    }

    public static String fileMd5 (InputStream inputStream) {
        try {
            return DigestUtils.md5Hex(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getPath () {
        return "/" + LocalDate.now().toString().replace("-", "/") + "/";
    }

    /**
     * 将文本写入文件
     * @param value
     * @param path
     */
    public static void saveTextFile (String value, String path) {
        FileWriter writer = null;
        try {
            File file = new File(path);
            if (! file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            writer = new FileWriter(file);
            writer.write(value);
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static String getText (String path) {
        File file = new File(path);
        if (! file.exists()) {
            return null;
        }
        try {
            return getText(new FileInputStream(file));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getText (InputStream inputStream) {
        InputStreamReader isr = null;
        BufferedReader bufferedReader = null;
        try {
            isr = new InputStreamReader(inputStream, "utf-8");
            bufferedReader = new BufferedReader(isr);
            StringBuilder builder = new StringBuilder();
            String string;
            while ((string = bufferedReader.readLine()) != null) {
                string = string + "\n";
                builder.append(string);
            }

            return builder.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (isr != null) {
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * 移动文件
     * @param branch       公司
     * @param questionType 类别
     * @param filePath     初始路径
     * @return
     */
    public static String moveFiles (String branch, String questionType, String filePath) {
        File startFile = new File(filePath);
        String fileName = startFile.getName();
        String replace = filePath.replace(fileName, "");
        String endPath = replace + branch + "/" + questionType + "/" + new SimpleDateFormat("yyyy/MM/dd/").format(new Date());
        try {
            //获取文件夹路径
            File tmpFile = new File(endPath);
            //判断文件夹是否创建，没有创建则创建新文件夹
            if (! tmpFile.exists()) {
                tmpFile.mkdirs();
            }
            log.info(endPath + startFile.getName());
            if (startFile.renameTo(new File(endPath + startFile.getName()))) {
                log.info("文件移动成功！文件名：《{}》 目标路径：{}", fileName, endPath);
                return endPath + startFile.getName();
            } else {
                log.info("文件移动失败！文件名：《{}》 起始路径：{}", fileName, filePath);
            }
        } catch (Exception e) {
            log.info("文件移动异常！文件名：《{}》 起始路径：{}", fileName, filePath);
        }
        return "";
    }

        /**
         * 普通java文件下载方法，适用于所有框架
         * @param request
         * @param res
         * @param filePaths 需要打包下载的文件路径集合 路径必须是绝对路径 否则无法下载
         * @param zipBasePath 下载文件压缩包之前，必须创建一个空的文件压缩包(下载完成之后删除压缩文件包)，zipBasePath 是此文件压缩包所在的文件目录
         * @param zipName 下载压缩包的名称
         * @return
         * @throws IOException
         */
        public  static String downloadFilesTest(HttpServletRequest request, HttpServletResponse res, List<String> filePaths, String zipBasePath, String zipName) throws IOException {
            //将附件中多个文件进行压缩，批量打包下载文件
            String zipFilePath = zipBasePath+ File.separator+zipName;
            //IO流实现下载的功能
            res.setContentType("text/html; charset=UTF-8"); //设置编码字符
            res.setContentType("application/octet-stream"); //设置内容类型为下载类型

            if(isMSBrowser(request)){
                // ie
                zipName = URLEncoder.encode(zipName, "UTF-8");
                res.setHeader("Content-disposition", "attachment;filename="+zipName);

            }else{
                // 如果是谷歌、火狐则解析为ISO-8859-1
                res.setHeader("Content-disposition", "attachment;filename="+new String(zipName.getBytes(),"iso-8859-1"));//设置下载的文件名称

            }

            res.setHeader("Set-Cookie", "fileDownload=true; path=/");
            OutputStream out = res.getOutputStream();
            //压缩文件
            File zip = new File(zipFilePath);
            if (!zip.exists()){
                zip.createNewFile();
            }
            //创建zip文件输出流
            ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
            zipFile(zipBasePath,zipName, zipFilePath,filePaths,zos);
            zos.close();
            res.setHeader("Content-disposition", "attachment;filename="+new String(zipName.getBytes(),"iso-8859-1"));

            //将打包后的文件写到客户端，输出的方法同上，使用缓冲流输出
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(zipFilePath));
            byte[] buff = new byte[bis.available()];

            bis.read(buff);
            bis.close();
            out.write(buff);//输出数据文件
            out.flush();//释放缓存
            out.close();//关闭输出流
            return null;
        }
        /**
         * 压缩文件
         * @param zipBasePath 临时压缩文件基础路径
         * @param zipName 临时压缩文件名称
         * @param zipFilePath 临时压缩文件完整路径
         * @param filePaths 需要压缩的文件路径集合
         * @throws IOException
         */
        public static String zipFile(String zipBasePath, String zipName, String zipFilePath, List<String> filePaths, ZipOutputStream zos) throws IOException {

            //循环读取文件路径集合，获取每一个文件的路径
            for (String filePath : filePaths) {
                File inputFile = new File(filePath);  //根据文件路径创建文件
                if (inputFile.exists()) { //判断文件是否存在
                    if (inputFile.isFile()) {  //判断是否属于文件，还是文件夹
                        //创建输入流读取文件
                        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(inputFile));

                        //将文件写入zip内，即将文件进行打包
                        zos.putNextEntry(new ZipEntry(inputFile.getName()));

                        //写入文件的方法，同上
                        int size = 0;
                        byte[] buffer = new byte[1024 * 1024];  //设置读取数据缓存大小
                        while ((size = bis.read(buffer)) > 0) {
                            zos.write(buffer, 0, size);
                        }
                        //关闭输入输出流
                        zos.closeEntry();
                        bis.close();

                    } else {  //如果是文件夹，则使用穷举的方法获取文件，写入zip
                        try {
                            File[] files = inputFile.listFiles();
                            List<String> filePathsTem = new ArrayList<String>();
                            for (File fileTem : files) {
                                filePathsTem.add(fileTem.toString());
                            }
                            return zipFile(zipBasePath, zipName, zipFilePath, filePathsTem, zos);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            return null;
        }

          // 判断是否是IE浏览器
          public static boolean isMSBrowser(HttpServletRequest request) {
              String[] IEBrowserSignals = {"MSIE", "Trident", "Edge"};
              String userAgent = request.getHeader("User-Agent");
              for (String signal : IEBrowserSignals) {
                  if (userAgent.contains(signal)) {
                      return true;
                  }
              }
              return false;
          }




}
